#include "linked_queue.h"
#include <stdlib.h>

#include "linear_linked_list.h"


/**
 * @brief 初始化队列
 * 初始化时，申请一个链队列head（类似于链表的head），队列头和尾都指向head
 * @param queue 队列
 */
LinkedQueueStatus_t LinkedQueueInit(LinkedQueue_t *queue)
{
    QueueNode_t *head = malloc(sizeof(QueueNode_t));
    if (!head) {
        return LINKED_QUEUE_FAIL;
    }
    head->next = NULL;

    queue->front = head;
    queue->rear = head;
    return LINKED_QUEUE_SUCCESS;
}

/**
 * @brief 判断队列是否为空
 * 当队列头位置和尾位置相同时，队列为空
 * @param queue 队列
 */
bool LinkedQueueIsEmpty(const LinkedQueue_t *queue)
{
    return queue->front == queue->rear;
}

/**
 * @brief 入队
 * @param queue 队列
 * @param data {@UserInfo_t}
 * @return {@LinkedQueueStatus_t}
 */
LinkedQueueStatus_t LinkedQueueIn(LinkedQueue_t *queue, const UserInfo_t *data)
{
    QueueNode_t *newNode = malloc(sizeof(QueueNode_t));
    if (!newNode) {
        return LINKED_QUEUE_FAIL;
    }
    newNode->data = *data;
    newNode->next = NULL;
    queue->rear->next = newNode;
    queue->rear = queue->rear->next;

    return LINKED_QUEUE_SUCCESS;
}

/**
 * @brief 出队
 * @param queue 队列
 * @param data {@UserInfo_t}
 * @return {@LinkedQueueStatus_t}
 */
LinkedQueueStatus_t LinkedQueueOut(LinkedQueue_t *queue, UserInfo_t *data)
{
    if (LinkedQueueIsEmpty(queue)) {
        return LINKED_QUEUE_FAIL;
    }
    QueueNode_t *target = queue->front->next;
    *data = target->data;
    if (target->next == NULL) { // 只剩一个节点
        queue->rear = queue->front;
        queue->front->next = NULL;
    } else { // 剩多个节点
        queue->front->next = target->next;
    }
    free(target);
    return LINKED_QUEUE_SUCCESS;
}

/**
 * @brief 获取队列头
 * @param queue 队列
 * @param data {@UserInfo_t}
 * @return {@LinkedQueueStatus_t}
 */
LinkedQueueStatus_t LinkedQueueGetFront(const LinkedQueue_t *queue, UserInfo_t *data)
{
    if (LinkedQueueIsEmpty(queue)) {
        return LINKED_QUEUE_FAIL;
    }
    *data = queue->front->next->data;
    return LINKED_QUEUE_SUCCESS;
}

void LinkedQueueDestroy(LinkedQueue_t *queue)
{
    while (queue->front != NULL) {
        QueueNode_t *curr = queue->front;
        queue->front = queue->front->next;
        free(curr);
    }
}